﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Core.LockStep
{
    public interface IDataContainer
    {
        DataEnumerator GetDataEnumerator();
        void AddData(IStreamData data);
        void Clear();
    }

    public class DataContainer<T> : IDataContainer where T : IStreamData
    {
        public List<T> datas = new List<T>();

        public virtual void AddData(IStreamData data)
        {
            datas.Add((T)data);
        }

        public IDataEnumerable<T> GetEnumerable()
        {
            return new DataEnumerable<T>(this);
        }

        public DataEnumerator GetDataEnumerator()
        {
            return new DataEnumerator(datas);
        }

        public virtual void Clear()
        {
            foreach (var item in datas)
                PoolTools.Push(item);
            datas.Clear();
        }
    }

    public interface IBackupDataContainer : IDataContainer
    {
        public IBackupData GetData(int backupId);
    }

    public class BackupDataContainer<T> : DataContainer<T>, IBackupDataContainer where T : IBackupData
    {
        public Dictionary<int, T> backupKeys = new Dictionary<int, T>();

        public override void AddData(IStreamData data)
        {
            var target = (T)data;
            datas.Add(target);
            backupKeys.Add(target.InstanceId, target);
        }

        public IBackupData GetData(int backupId)
        {
            if (backupKeys.TryGetValue(backupId, out var data))
                return data;
            return null;
        }

        public override void Clear()
        {
            foreach (var item in datas)
                PoolTools.Push(item);
            datas.Clear();
            backupKeys.Clear();
        }
    }

    public struct DataEnumerator
    {
        public IStreamData current;

        private IList datas;

        private int index;

        public DataEnumerator(IList datas)
        {
            this.datas = datas;
            current = null;
            index = 0;
        }

        public bool MoveNext()
        {
            if (index >= datas.Count)
                return false;

            current = (IStreamData)datas[index++];
            return true;
        }
    }
}